<!-- 注意事项
  1，渲染table的数据来源有两种：通过tableHeader和tableData传入数据或则通过传入api和params在组件内请求数据
  2，开启多选时，组件需要设置 v-model:selection="***" , 否则悬浮框会显示异常
-->
<template>
  <div class="custom-table" ref="customTableRef" :style="{ height: height }">
    <CustomSearch ref="searchRef" :title="searchTitle" :formItemList="formItemList" v-model:form="form" :lowcode="'pzid' in props.params" @search="getData" :columns="columns" style="margin-bottom: 10rem"></CustomSearch>

    <div class="table-wrap">
      <el-row v-if="'tableTop' in $slots">
        <el-col :span="16">
          <div class="top-buttons">
            <slot name="tableTop" :rows="selection" :row="rowData">
              <el-button type="primary" v-for="(item, index) in buttons" :key="index" :disabled="Object.keys(rowData).length == 0" @click="onBtnClick(item.anType, rowData, selection)"> {{ item.name }}</el-button>
            </slot>
          </div>
        </el-col>
        <el-col :span="6">
          <!-- <el-button type="primary" size="small" plain>导出</el-button>
          <el-button type="primary" size="small" plain @click="print"
            >打印</el-button
          > -->
        </el-col>
        <el-col :span="2">
          <!-- <el-popover popper-class="table-header-popper" placement="bottom" title="请选择要显示的列名" :width="200" trigger="hover" content="" :hide-after="20">
            <el-tree style="max-width: 200px" :data="props.tableHeader" node-key="key" show-checkbox check-on-click-node draggable :allow-drop="allowDrop" :default-checked-keys="defaultCheckedKeys" @check-change="handleNodeClick" />
            <template #reference>
              <el-icon size="16"><Setting /></el-icon>
            </template>
          </el-popover>
          <el-icon size="18" class="refresh-table" @click="getData(searchRef.formatParams())"><Refresh /></el-icon> -->
        </el-col>
      </el-row>
      <div class="table-box">
        <el-table
          ref="tableRef"
          stripe
          style="width: 100%"
          v-loading="loading"
          :row-key="(row) => row.ID || row.id || JSON.stringify(row)"
          :data="dataSource"
          :row-class-name="setRowClass"
          :class="!switchBgColor ? 'before-change' : 'after-change'"
          :default-sort="defaultSort"
          :highlight-current-row="highlightCurrentRow"
          :show-header="showHeader"
          :border="border"
          @current-change="onCurrentChange"
          @sort-change="onSortChange"
          @cell-click="onCellClick"
          @row-click="onRowClick"
          @select="onSelect"
          @select-all="onSelectAll"
          @selection-change="onSelectionChange"
          @row-contextmenu="onRowContextmenu"
        >
          <el-table-column :align="align" v-if="type && headerSource.length > 0" :index="indexMethod" :type="type" label="序号" width="80"> </el-table-column>
          <el-table-column
            v-for="(item, index) in headerSource"
            :key="index"
            :prop="item.key"
            :label="item.label"
            :min-width="item.width || '100rem'"
            :show-overflow-tooltip="showOverflowTtooltip"
            :class-name="item.key"
            :align="align"
            :sortable="item.sortable || sortable"
            :fixed="item.key == 'CZ' ? 'right' : null"
          >
            <template v-slot="{ row }">
              <template v-if="item.key != 'CZ'">
                <!-- <slot :name="item.key" :row="row"> {{ row[item.key] !== null ? row[item.key] : '暂无数据' }}</slot> -->
                <slot :name="item.key" :row="row"> {{ row[item.key] }}</slot>
              </template>
              <!-- 接口返回了操作按钮 -->
              <template v-else>
                <slot :name="item.key" :row="row">
                  <el-button type="primary" @click="onBtnClick('view', row)"> {{ row[item.key] }}</el-button>
                </slot>
              </template>
            </template>
          </el-table-column>

          <el-table-column :[widthOrMinWidth]="colWidth" v-if="'lastColumn' in $slots && headerSource.length > 0" :align="align" label="操作" fixed="right">
            <template v-slot="{ row }">
              <slot name="lastColumn" :row="row"></slot>
            </template>
          </el-table-column>
          <template #empty>
            <CustomEmpty height="700rem" />
          </template>
        </el-table>
      </div>
      <CustomPagination v-if="props.showPagination" v-model:current-page="pageNumber" v-model:page-size="pageSize" :total="total" @getData="getData"></CustomPagination>
      <!-- 右键菜单插槽 -->
      <div v-if="showContextMenu" id="contextMenu" class="context-menu">
        <slot name="contextMenu" :row="rowData"></slot>
      </div>
    </div>

    <FloatWindow v-if="props.type == 'selection' && selection.length > 0 && props.multiple && showPagination" :header="headerSource" v-model:selection="selection" :tableData="tableData" v-drag="{ top: 160, right: 200 }" />
  </div>
</template>

<script setup name="CustomTable">
import { ref, unref, onMounted, onBeforeUnmount, computed, watch, getCurrentInstance, onActivated, onDeactivated, nextTick } from 'vue'
import { useRoute } from 'vue-router'
import { http } from '@/utils/index'
import { stores } from '@/stores/index.js'
import FloatWindow from './FloatWindow.vue'
import { ElMention, ElMessage } from 'element-plus'

const userStore = stores.useUserStore()

const loading = defineModel('loading')
// const formItemList = defineModel('formItemList', { default: [] }) //表头搜索项
const form = defineModel('form', { default: {} }) // 表头搜索项
const selection = defineModel('selection', { default: [] })
const showContextMenu = defineModel('showContextMenu', { default: false })
const props = defineProps({
  type: {
    type: String,
    default: '' //index或者selection
  },

  height: {
    type: [String, Number],
    default: '100%'
  },
  //tableheader  的高度
  thHeiht: {
    type: [String, Number],
    default: '45rem'
  },
  //行的高度
  tdHeiht: {
    type: [String, Number],
    default: '50rem'
  },
  tableHeader: {
    type: Array,
    default: () => {
      return [
        // 示例数据
        // {
        //   key: "name",
        //   label: "姓名"
        //   //width: '25%'
        // },
        // {
        //   key: "age",
        //   label: "年龄"
        //   //width: '25%'
        // },
        // {
        //   key: "address",
        //   label: "住址"
        //   //width: '50%'
        // }
      ]
    }
  },
  tableData: {
    type: Array,
    default: () => {
      return [
        // 示例数据
        // {
        //   name: '张三',
        //   age: '18',
        //   address: '天安云谷601'
        // }
      ]
    }
  },
  showPagination: {
    type: Boolean,
    default: true
  },

  border: {
    type: Boolean,
    default: true
  },
  sortable: {
    type: Boolean,
    default: false
  },
  //是否可多选
  multiple: {
    type: Boolean,
    default: false
  },
  align: {
    type: String,
    default: 'center'
  },
  defaultSort: {
    type: Object,
    default: () => {
      return {}
    }
  },
  // searchTitle: {
  //   type: String,
  //   default: ""
  // },
  //搜索条件显示的字段
  searchField: {
    type: Array,
    default: () => {
      return []
    }
  },
  api: {
    type: String,
    default: '/thjy/query/getConfigData'
  },
  //请求接口需要的参数
  params: {
    type: Object,
    default: () => {
      return {}
    }
  },
  requestImmediate: {
    //是否立即请求数据
    type: Boolean,
    default: true
  },
  // 必须要传的参数，如果没有传入并给出相应的提示
  requiredParamsValidate: {
    type: Object,
    default: () => {
      return {
        // dwdm:'请先在左侧选择单位'
      }
    }
  },

  method: {
    type: String,
    default: 'get'
  },
  oddColor: {
    //斑马纹奇数行背景色
    type: String,
    default: ''
  },
  evenColor: {
    //斑马纹偶数行背景色
    type: String,
    default: ''
  },
  showHeader: {
    type: Boolean,
    default: true
  },
  showOverflowTtooltip: {
    type: Boolean,
    default: true
  },
  highlightCurrentRow: {
    type: Boolean,
    default: true
  },
  // loading: {
  //   type: Boolean,
  //   default: false
  // },
  //是否滚动显示
  scroll: {
    type: Boolean,
    default: false
  },
  scrollSpeed: {
    type: [String, Number],
    default: 5
  },

  //设置操作列的最小宽度(要设置成百分比，且其他列也要设置百分比宽度才会自适应宽度)
  lastColMinWidth: {
    type: [String, Number],
    default: ''
  },
  //设置操作列的宽度
  lastColWidth: {
    type: [String, Number],
    default: ''
  },
  columns: {
    //搜索栏每行显示几列
    type: [String, Number],
    default: 5
  },

  stringify: {
    //通过api请求数据时，是否序列化参数
    type: Boolean,
    default: true
  }
})
const formItemList = ref([])
const emit = defineEmits(['setRowClass', 'onCellClick', 'selection ', 'row-click', 'onRowContextmenu', 'onBtnClick'])
const customTableRef = ref()
const tableHeight = ref('100px')
const tableRef = ref()
const btnType = ref('')
const searchRef = ref()
const searchTitle = ref('')
const route = useRoute()
const instance = getCurrentInstance()
const searchForm = ref({})
const thePropsTableHeader = ref(props.tableHeader)
//接口返回的tableHeader
const tableHeader = ref([])
const tableData = ref([])
const buttons = ref([])
// 选中的当前行数据
const rowData = ref({})
// 选中的所有行
const pageNumber = ref(1)
const pageSize = ref(20)
const total = ref(0)
//tableHeader数据来源
const headerSource = computed(() => {
  if (thePropsTableHeader.value.length > 0) {
    return thePropsTableHeader.value.filter((item) => item.hidden !== true)
  } else if (props.requestApi != '') {
    return tableHeader.value.filter((item) => item.hidden !== true)
  } else {
    return []
  }
})
//选择要显示的表头列名
const defaultCheckedKeys = computed(() => {
  return headerSource.value.map((item) => item.key)
})
//tableData数据来源
const dataSource = computed(() => {
  if (props.tableData.length > 0) {
    if (startScroll.value) {
      return props.tableData.concat(props.tableData)
    } else {
      return props.tableData
    }
  } else {
    return tableData.value
  }
})

//操作列宽度属性使用min-width 还是width
const widthOrMinWidth = computed(() => {
  return props.lastColMinWidth != '' ? 'min-width' : 'width'
})

//操作列的宽度
const colWidth = computed(() => {
  return widthOrMinWidth == 'width' ? props.lastColWidth : props.lastColMinWidth
})
const scrollbarWrapHeight = ref(0)
const scrollbarViewHeight = ref(0)
//开启滚动时，是否需要切换奇数行和偶数行的背景色
const switchBgColor = ref(false)
const startScroll = ref(false)
const animationDuration = ref('5s')

//将searchField数组转换成对象的形式并v-model到CustomSearch组件上
// props.searchField.forEach((item) => {
//   formItemList.value[item] = ''
// })
watch(
  () => props.params,
  (newVal, oldValue) => {
    selection.value = []
  },
  {
    deep: true
    // immediate: true
  }
)
watch(
  () => props.selection,
  (newVal) => {
    sessionStorage.setItem('customTable', JSON.stringify(newVal))
  },
  {
    deep: true
  }
)
watch(
  () => props.tableHeader,
  (newVal) => {
    thePropsTableHeader.value = newVal
  }
)
watch(dataSource, async (newVal) => {
  tableRef.value.clearSelection()
  await nextTick()
  selection.value.forEach((item) => {
    const row = newVal.find((obj) => JSON.stringify(obj) == JSON.stringify(item))
    if (row) {
      tableRef.value.toggleRowSelection(row, true)
    }
  })
})
onBeforeUnmount(() => {
  selection.value = []
})
onMounted(() => {
  if (props.requestImmediate) {
    getData()
  }

  if (props.scroll) {
    initScorll()
  }
})

onActivated(() => {
  // console.log('CustomTable Activated！')
  //当页面需要刷新时，重置search组件v-model绑定的对象
  if (route.meta && route.meta.refresh === true) {
    searchRef.value.reset()
  }
  //页面使用缓存时，返回该页面时保持表格滚动的位置

  const tbodyWrap = customTableRef.value && customTableRef.value.querySelector('.el-scrollbar__wrap')
  if (tbodyWrap) {
    tbodyWrap.onscroll = function () {
      sessionStorage.setItem('tableScrollingPosition', tbodyWrap.scrollTop)
    }
    tbodyWrap.scrollTop = sessionStorage.getItem('tableScrollingPosition')
  }
})
onDeactivated(() => {})

const getData = (params = {}) => {
  // console.log(params)
  // 如有必传参数没有传入，弹出错误提示。
  for (const key in props.requiredParamsValidate) {
    if (!props.params[key])
      return ElMessage.warning({
        type: 'warning',
        message: props.requiredParamsValidate[key],
        duration: 4000
      })
  }
  loading.value = true
  if ('pzid' in props.params) {
    http
      .get(props.api, {
        params: Object.assign({}, props.params, params, {
          pageSize: pageSize.value,
          pageNumber: pageNumber.value,
          dwlx: userStore.userInfor.dwlx,
          dwdm: userStore.userInfor.dwdm,
          orderBy: '',
          GYQX: ''
        })
      })
      .then(async (res) => {
        formItemList.value = res.data.form
        searchTitle.value = res.data.ymm
        total.value = res.data.totalRecord
        buttons.value = res.data.buttons || []
        tableHeader.value = res.data.tableTh.filter((item) => item.key != 'ID')
        // await nextTick();
        const arr = []
        res.data.tableData.forEach((item) => {
          const obj = {}
          item.forEach((subItem) => {
            obj[subItem.field] = subItem.value
          })
          arr.push(obj)
        })
        tableData.value = arr
        selection.value = JSON.parse(sessionStorage.getItem('customTable')) || []
        await nextTick()
        selection.value.forEach((item) => {
          tableData.value.forEach((subItem) => {
            if (JSON.stringify(item) == JSON.stringify(subItem)) {
              tableRef.value.toggleRowSelection(subItem, true)
            }
          })
        })
        // await nextTick()
        // tableRef.value.doLayout()
      })
      .finally(() => {
        loading.value = false
      })
  } else {
    http(
      props.api,
      props.method,
      Object.assign({}, props.params, params, {
        pageNum: props.showPagination ? pageNumber.value : null,
        pageSize: props.showPagination ? pageSize.value : null
      })
    )
      .then((res) => {
        tableData.value = res.data.records || res.data
        total.value = res.data.total
      })
      .finally(() => {
        loading.value = false
      })
  }
}
//排序
const onSortChange = ({ prop, order }) => {
  getData({
    orderByColumn: prop,
    orderType: order == 'descending' ? 'desc' : 'asc'
  })
}

//勾选数据行的 Checkbox 时触发的事件
const onSelect = (selection, row) => {
  onRowClick(row)
}

//某一行的选中状态发生了变化
const onCurrentChange = (row, column, event) => {
  // emit('row-click', row)
  // if (props.multiple) {
  //   handleMultiple(row)
  // }
}
const onRowClick = async (row, column, event) => {
  rowData.value = row
  const index = selection.value.findIndex((item) => JSON.stringify(row) == JSON.stringify(item))
  //多选
  if (props.multiple) {
    if (index == -1) {
      tableRef.value.toggleRowSelection(row, true)
      selection.value.push(row)
    } else {
      selection.value.splice(index, 1)
      await nextTick()

      tableRef.value.toggleRowSelection(row, false)
    }
  } else {
    tableRef.value.clearSelection()
    if (index == -1) {
      tableRef.value.toggleRowSelection(row, true)
      selection.value = []
      await nextTick()
      selection.value.push(row)
    } else {
      selection.value = []
    }
  }
}

//选项发生变化时触发
const onSelectionChange = async (newSelection) => {}
//全选
const onSelectAll = (arr) => {
  if (arr.length > 0) {
    selection.value = Array.from(new Set([...selection.value, ...arr]))
  } else {
    dataSource.value.forEach((item) => {
      const index = selection.value.findIndex((x) => JSON.stringify(x) == JSON.stringify(item))
      if (index != -1) {
        selection.value.splice(index, 1)
      }
    })
  }
}
//选择显示头部列名
const handleNodeClick = (node, checked) => {
  console.log(checked)
  const item = thePropsTableHeader.value.find((item) => item.key == node.key)
  const length = thePropsTableHeader.value.filter((item) => item.hidden !== true).length
  console.log(length)
  if (length > 1) {
    if (checked === false) {
      item.hidden = true
    } else {
      item.hidden = false
    }
  }

  console.log(item)
  // if (thePropsTableHeader.value.length > 0) {
  //   const newHeader = []
  //   // console.log(props.tableHeader)
  //   checked.checkedKeys.forEach((item) => {
  //     const column = props.tableHeader.find((v) => v.key == item)
  //     if (column) {
  //       newHeader.push(column)
  //     }
  //   })
  //   thePropsTableHeader.value = newHeader
  // }
}
//tree节点可拖动的位置
const allowDrop = (draggingNode, dropNode, type) => {
  return type == 'inner' ? false : true
}
//初始化滚动
const initScorll = () => {
  setTimeout(() => {
    const scrollbarWrap = customTableRef.value.querySelector('.el-scrollbar__wrap')
    let scrollbarView = customTableRef.value.querySelector('.el-scrollbar__view')
    scrollbarWrapHeight.value = scrollbarWrap.offsetHeight
    scrollbarViewHeight.value = scrollbarView.offsetHeight
    //内容未超出容器不滚动
    if (scrollbarViewHeight.value < scrollbarWrapHeight.value) return
    startScroll.value = true

    nextTick(() => {
      scrollbarView = customTableRef.value.querySelector('.el-scrollbar__view')
      scrollbarViewHeight.value = scrollbarView.offsetHeight

      animationDuration.value = Math.floor(scrollbarViewHeight.value / (props.scrollSpeed * 20)) + 's'

      //不显示滚动条
      scrollbarWrap.style.overflow = 'hidden'

      // 设置第一次滚动动画
      const firstScroll = `@keyframes firstScroll {
        0% {
          transform: translateY(0);
        }
        100% {
          transform: translateY(${scrollbarWrapHeight.value - scrollbarViewHeight.value}px);
        }
      }`
      const style = document.createElement('style')
      style.innerHTML = firstScroll
      customTableRef.value.querySelector('.el-scrollbar__view').appendChild(style)
      scrollbarView.addEventListener('animationend', infiniteScorll)
      scrollbarView.style.animation = `firstScroll ${animationDuration.value} linear`
    })

    // })
  }, 2000)
}
//无限滚动
const infiniteScorll = (e) => {
  switch (e.type) {
    case 'animationend':
      e.target.addEventListener('animationend', infiniteScorll)
      changeColor()
      e.target.addEventListener('animationiteration', changeColor)
      const infiniteScorllKey = `@keyframes infiniteScorll {
          0% {
            transform: translateY(${scrollbarWrapHeight.value - scrollbarViewHeight.value / 2}px);
          }
          100% {
            transform: translateY(${scrollbarWrapHeight.value - scrollbarViewHeight.value}px);
          }
        }`
      const style = document.createElement('style')
      style.innerHTML = infiniteScorllKey
      e.target.appendChild(style)
      e.target.style.animation = `infiniteScorll ${animationDuration.value} linear infinite`
    case 'animationiteration':
      // changeColor()
      //table设置了斑马纹背景且数据条数是奇数时滚动显示内容，防止页面闪动
      // if (dataSource.value.length % 2 == 0) {
      //   return
      // } else {
      //   switchBgColor.value = !switchBgColor.value
      // }
      break
  }
}
const changeColor = () => {
  if (props.tableData.length % 2 == 0) {
    // console.log('不改变颜色')
    return
  } else {
    // console.log('要改变颜色')

    switchBgColor.value = !switchBgColor.value
    // e.target.style.animation = 'infiniteScorll 9s linear infinite'
  }
}

//设置行的class名称
const setRowClass = ({ row }) => {
  if (row.XM == '张三8') {
    return 'gold'
  } else if (row.XM == '张三3') {
    return 'teal'
  } else if (row.XM == '张三6') {
    return 'red'
  } else {
    //也可以在外部定义样式，并通过回调传入类名,
    var class_name = ''
    function callback(className) {
      class_name = className
    }
    emit('setRowClass', row, callback)
    return class_name
  }
}

const onCellClick = (row, column, cell, event) => {
  emit('onCellClick', row, column, cell, event)
}
const onBtnClick = (btnType, row, rows) => {
  emit('onBtnClick', btnType, row, rows)
}
// 鼠标右键单击事件(通过contextMenu插槽名称传入右键菜单要显示的内容)
const onRowContextmenu = async (row, column, event) => {
  showContextMenu.value = true
  await nextTick()

  rowData.value = row
  const tableWrap = customTableRef.value.querySelector('.table-wrap')
  const rect = tableWrap.getBoundingClientRect()
  const menu = tableWrap.querySelector('#contextMenu')
  //超出了右边界
  if (event.pageX - rect.left > rect.width - menu.offsetWidth) {
    menu.style.left = rect.width - menu.offsetWidth + 'px'
  } else {
    menu.style.left = event.pageX - rect.left + 10 + 'px'
  }
  //超出了下边界
  if (event.pageY - rect.top > rect.height - menu.offsetHeight) {
    menu.style.top = rect.height - menu.offsetHeight + 'px'
  } else {
    menu.style.top = event.pageY - rect.top + 10 + 'px'
  }
  menu.style.zIndex = 1
  emit('onRowContextmenu', row)
}
const indexMethod = (index) => {
  return (pageNumber.value - 1) * pageSize.value + (index + 1)
}

defineExpose({
  tableRef,
  getData,
  dataSource
})
</script>
<style lang="scss" scoped>
.custom-table {
  display: flex;
  flex-direction: column;
  width: 100%;

  .refresh-table {
    margin-left: 15px;
    cursor: pointer;
  }
  .top-buttons {
    padding: 5px 0;
  }

  .table-wrap {
    width: 100%;
    padding: 13px;
    height: 100px;
    // margin-top: 10px;
    position: relative;
    flex: auto;
    display: flex;
    flex-direction: column;
    border: var(--el-border);
    // box-shadow: var(--el-box-shadow-light);
    background-color: #fff;
    border-radius: 4px;
    .el-row {
      margin-bottom: 5px;
    }
    .table-box {
      flex: auto;
      overflow: hidden;
      ::v-deep(.el-table) {
        height: 100%;
        &::after,
        &::before {
          display: none;
          background: none !important;
        }

        .el-table__header th {
          background-color: var(--el-fill-color-light);
        }

        .el-scrollbar__view:hover {
          animation-play-state: paused !important;
        }

        .el-table__inner-wrapper::after,
        .el-table__inner-wrapper:before {
          display: none;
        }

        th.el-table__cell {
          height: v-bind(thHeiht);
          padding: 0;
          font-size: 16px;
        }

        td.el-table__cell {
          height: v-bind(tdHeiht);
          padding: 0;
          font-size: 16px;
        }

        th.el-table__cell {
          .cell {
            white-space: nowrap;
          }
        }

        td.el-table__cell {
          .cell {
            color: #9e9e9e;
            white-space: nowrap;
          }
        }

        td.el-table__cell,
        th.el-table__cell.is-leaf {
          // border-bottom: none;
        }

        .el-checkbox__input .el-checkbox__inner {
          width: 20px;
          height: 20px;
        }

        .el-checkbox__input.is-checked .el-checkbox__inner:after {
          top: 3px !important;
          left: 8px !important;
          width: 4px !important;
          height: 8px !important;
        }
        tr.red .cell {
          color: red !important;
        }
        //自定义行的样式
        tr.gold {
          td {
            background-color: lightseagreen !important;
          }
          .cell {
            color: gold !important;
          }
        }
        tr.teal .cell {
          color: teal !important;
        }
      }
    }
  }

  //设置奇数行背景色， before-change 和 after-change 为表格滚动时否切换背景色的样式
  // ::v-deep(.before-change) {
  //   tr:nth-child(odd) {
  //     background-color: v-bind(oddColor);
  //   }

  //   tr:nth-child(even) {
  //     background-color: v-bind(evenColor);
  //   }
  // }
  // // //设置奇数行背景色
  // ::v-deep(.after-change) {
  //   tr:nth-child(odd) {
  //     background-color: v-bind(evenColor);
  //   }

  //   tr:nth-child(even) {
  //     background-color: v-bind(oddColor);
  //   }
  // }
  //右键弹框样式
  .context-menu {
    position: absolute;
  }
}
</style>
<style lang="scss">
.el-popper.table-header-popper {
  .el-tree-node {
    padding-left: 15px;
  }
  .el-tree-node__expand-icon {
    display: none;
  }
}
</style>
